#include<iostream>
#include<pthread.h>
#include <unistd.h>
using namespace std;

#define NUM 5

//死锁问题：死锁是指在一组进程中的各个进程均占有不会释放的资源，但因互相申请被其他进程所站用不会释放的资
//源而处于的一种永久等待状态。
// pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
// pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;
// void* thread1(void* arg)
// {
//     // 线程1先锁定mutex1
//     pthread_mutex_lock(&mutex1);
//     printf("Thread 1 acquired mutex1\n");

//     // 然后尝试锁定mutex2
//     pthread_mutex_lock(&mutex2);
//     printf("Thread 1 acquired mutex2\n");
    
//     pthread_mutex_unlock(&mutex1);
//     pthread_mutex_unlock(&mutex2);

//     return NULL;
// }

// void* thread2(void* arg)
// {
//     // 线程2先锁定mutex2
//     pthread_mutex_lock(&mutex2);
//     printf("Thread 2 acquired mutex2\n");

//     // 然后尝试锁定mutex1
//     pthread_mutex_lock(&mutex1);
//     printf("Thread 2 acquired mutex1\n");
    
//     pthread_mutex_unlock(&mutex2);
//     pthread_mutex_unlock(&mutex1);

//     return NULL;
// }

// int main()
// {
//     pthread_t tid1, tid2;

//     pthread_create(&tid1, NULL, thread1, NULL);
//     pthread_create(&tid2, NULL, thread2, NULL);

//     pthread_join(tid1, NULL);
//     pthread_join(tid2, NULL);
//     return 0;
// }
//创建了两个线程，线程1首先锁定mutex1，然后尝试锁定mutex2。同时，线程2首先锁定mutex2，然后尝试锁定mutex1。
//这将导致两个线程在等待对方释放资源的情况下陷入死锁。


//线程的同步--条件变量
//首先要理解清楚一些概念：
//同步就是协同步调，按预定的先后次序进行运行。如：你说完，我再说。是指协同、协助、互相配合。
//线程同步是指多线程通过特定的设置（如互斥量，事件对象，临界区）来控制线程之间的执行顺序（即所谓的同步）从而有效避免饥饿问
//题，也可以说是在线程之间通过同步建立起执行顺序的关系，如果没有同步，那线程之间是各自运行各自的！

//线程互斥是指对于共享的进程系统资源，在各单个线程访问时的排它性。
//当有若干个线程都要使用某一共享资源时，任何时刻最多只允许一个线程去使用，其它要使用该资源的线程必须等待，直到占用资源者释放该资源。
//线程互斥可以看成是一种特殊的线程同步。

int cnt=0;
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t  cond=PTHREAD_COND_INITIALIZER;

void* count(void* args)
{
    pthread_detach(pthread_self());
    uint64_t number = (uint64_t)args;
    std::cout << "pthread: " << number << " create success" << std::endl;
     while(true)
    {
        pthread_mutex_lock(&mutex);
        // 我们怎么知道我们要让一个线程去休眠了那？一定是临界资源不就绪，没错，临界资源也是有状态的！！
        // 你怎么知道临界资源是就绪还是不就绪的？你判断出来的！判断是访问临界资源吗？必须是的，也就是判断必须在加锁之后！！！
       pthread_cond_wait(&cond, &mutex);               //？ 为什么在这里？ 1. pthread_cond_wait让线程等待的时候，会自动释放锁！
        // 不管临界资源的状态情况
        std::cout << "pthread: " << number << " ， cnt: " << cnt++ << std::endl;
        pthread_mutex_unlock(&mutex);
    }
}
int main()
{
    for(size_t i=0;i<NUM;i++)
    {
        pthread_t tid;
        pthread_create(&tid,nullptr,count,(void*)i);
         usleep(1000);
    }


   sleep(3);
    std::cout << "main thread ctrl begin: " << std::endl;
    while(true) 
    {
        sleep(1);
        // pthread_cond_signal(&cond); //唤醒在cond的等待队列中等待的一个线程，默认都是第一个
        pthread_cond_broadcast(&cond);//唤醒所有在cond的等待队列中等待的线程
        std::cout << "signal one thread..." << std::endl;
    } 

    return 0;
}